"""空调负荷监测业务逻辑模块"""
import traceback
from datetime import datetime, timedelta

import numpy as np

from air_web.config.config import config
from air_web.web_flask.bll.base_bll import BaseBll
from air_web.web_flask.bll.model_map import ModelMap
from air_web.web_flask.common.constants import ReturnType


class MonitorBll(BaseBll):
    """空调负荷监测业务逻辑类"""

    cons_no_field = "cons_no"
    POWERLOAD = config["POWERLOAD_MONITOR"]
    POWERLOAD_AREA = config["POWERLOAD_AREA_MONITOR"]

    ALERT_TYPE_MAP = {1: 0.2, 2: 0.1, 3: 0.1}

    def __init__(self):
        """
        如果当前页面用到mysql则init_mysql_dal=True，self.sql_dal就会提供mysql实例，不用到则传False
        如果当前页面用到es则init_es_dal=True，self.es_dal就会提供es实例，不用到则传False
        """
        super().__init__(init_mysql_dal=True, init_es_dal=True)

    def get_powerload_index(self, cons_no):
        on7 = str(ModelMap.get("c_cons_all", "on7", db_key=cons_no))
        powerload_idx = self.POWERLOAD.replace("on5", on7[0:5]).replace(
            "on7", on7
        )
        self.logger.info("要查询的powerload索引:{}".format(powerload_idx))
        return powerload_idx

    def get_air_monitor(self, params):
        try:
            org_no = params.get("org_no")
            type_code = params.get("type_code")
            cons_no = params.get("cons_no")
            date_str = params.get("start_date")

            date_rules = [("data_time", "query", "=", date_str)]
            type_code_rules = (
                [("type_id", "query", "=", type_code)]
                if type_code
                else [
                    ("type_id", "query", "=", "99"),
                    ("type_code_sort", "query", "=", "99"),
                ]
            )

            if cons_no:
                rules = [
                    (self.cons_no_field, "query", "=", cons_no)
                ] + date_rules
                index_name = self.get_powerload_index(cons_no)
            else:
                rules = (
                    [("org_no", "query", "=", org_no)]
                    + date_rules
                    + type_code_rules
                )
                index_name = self.POWERLOAD_AREA
            res_df = self.es_dal.query_dataframe(
                rules,
                index_name,
                doc_time_field="data_time",
                source=["p_kt", "p_kt_actual", "data_time"],
            )
            print(rules)
            if res_df.empty:
                print(f"{index_name} is empty")
                return ReturnType.EMPTY
            res_df["data_time"] = res_df["data_time"].astype(str)
            res_df.sort_values(by=["data_time"], ascending=True, inplace=True)
            res = res_df.to_dict("record")
            return res

        except:
            self.logger.error(traceback.format_exc())
            return ReturnType.ERROR

    def get_alert_city(self, params):
        try:
            data_date = params.get("data_date")
            sql = "select on5, city_name, alert_type from city_alert where alert_time = %s"
            value = [data_date]

            res_df = self.sql_dal.sql_pandas.query(sql, params=value)
            if res_df.empty:
                print(f"city_alert {data_date} is empty")
                return ReturnType.EMPTY

            res = res_df.to_dict("record")
            return res

        except:
            self.logger.error(traceback.format_exc())
            return ReturnType.ERROR

    def get_someday_kt(self, on5, data_date):
        end_date = (
            datetime.strptime(data_date, "%Y-%m-%d") + timedelta(days=1)
        ).strftime("%Y-%m-%d")
        rules = [
            ("org_no", "query", "=", on5),
            ("data_time", "query", ">=", data_date),
            ("data_time", "query", "<", end_date),
            ("type_id", "query", "=", "0"),
        ]
        table_name = config.get("ORGNO_TYPEID_15MIN", "orgno_typeid_15min")
        res_df = self.sql_dal.sql_pandas.query_by_rules(
            table_name,
            rules,
            columns=["data_time", "p_kt_sum"],
            sort_field=["data_time"],
        )
        if res_df.empty:
            self.logger.warning(f"查询结果为空:{table_name}, {rules}")
            return res_df
        self.logger.info(f"查询:{table_name},结果数量:{len(res_df)}, {rules}")
        res_df = res_df.rename(columns={"p_kt_sum": "p_kt"})
        return res_df

    def get_city_graph(self, params):
        try:
            data_date = params.get("data_date")
            on5 = params.get("on5")
            alert_type = params.get("alert_type")

            res_df = self.get_someday_kt(on5, data_date)
            if res_df.empty:
                return ReturnType.EMPTY
            res_df["p_kt"] = (res_df["p_kt"] / 10000).round(2)

            pre_date = (
                datetime.strptime(data_date, "%Y-%m-%d") - timedelta(days=1)
            ).strftime("%Y-%m-%d")
            # pre_date = self.get_baseline_date(data_date)
            pre_df = self.get_someday_kt(on5, pre_date)
            if pre_df.empty:
                res_df["data_time"] = res_df["data_time"].astype(str)
                res_dict = res_df.to_dict("list")
                res_dict.update({"p_kt_baseline": [], "p_kt_target": []})
            else:
                pre_df["data_time"] = pre_df["data_time"] + timedelta(days=1)
                res_df = res_df.merge(
                    pre_df,
                    on="data_time",
                    how="right",
                    suffixes=("", "_baseline"),
                )
                res_df["p_kt_target"] = res_df["p_kt_baseline"] * (
                    1 - self.ALERT_TYPE_MAP[alert_type]
                )
                for col in ["p_kt_target", "p_kt_baseline"]:
                    res_df[col] = (res_df[col] / 10000).round(2)
                res_df["data_time"] = res_df["data_time"].astype(str)
                res_df = res_df.replace({np.nan: ""})
                res_dict = res_df.to_dict("list")

            return res_dict
        except:
            self.logger.error(traceback.format_exc())
            return ReturnType.ERROR
